/*
 * Saphre - Suffix Arrays for Phrase Extraction
 * Copyright (C) 2013 
 * Dale Gerdemann - Tübingen, Germany 
 * Niko Schenk - Frankfurt am Main, Germany
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
package saphre.core;

import util.tokenization_io.Normalizer;
import util.tokenization_io.GeneralNormalizer;
import util.tokenization_io.RegexTokenizer;
import util.tokenization_io.Tokenizer;
import util.Interval;
import util.tokenization_io.BoundarySymbols;

import java.io.File;
import java.util.*;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import saphre.concordance.Concordance;
import saphre.concordance.ConcordanceOverlap;
import util.sedgewick.Stopwatch;
import serialization.SaphreSerializerMeta;

/**
 * SaphreBase is a wrapper for all suffix array data structures
 * with appropriate getters and setters.
 * 
 * @authors Niko Schenk, Zeeshan Mustafa
 */
public class SaphreBase {

    String corpPath;
    private Tokenizer token;

    private Map<String, List<Interval>> delMap;

    private Store store;
    private int n;
    private SuffixArray sa;
    private Interval top;
    private Concordance concord;
    private ConcordanceOverlap concordOver;
    private boolean doSerialize = false;

    private String regexPath;
    private String normStrPath;

    private String boundaryPath;

    private UUID corpusId;

    public SaphreBase(Map<String, List<Interval>> delMap,
                      String corpPath,
                      String regexPath,
                      String normStrPath,
                      String boundaryPath,
                      boolean doSerialize,
                      UUID corpusId) {


        this.delMap = delMap;
        this.corpPath = corpPath;
        this.token = token;
        this.regexPath = regexPath;
        this.normStrPath = normStrPath;
        this.boundaryPath = boundaryPath;
        this.doSerialize = doSerialize;
        this.corpusId = corpusId;
    }

    
    
    public UUID getCorpusId() {
        return corpusId;
    }

    public void setCorpusId(UUID corpusId) {
        this.corpusId = corpusId;
    }

    private SaphreSerializerMeta serMeta;

    public SaphreSerializerMeta getSaphreSerializerMeta() {
        return serMeta;
    }

    public void setSaphreSerializerMeta(SaphreSerializerMeta serMeta) {
        this.serMeta = serMeta;
    }

    public String getRegexPath() {
        return regexPath;
    }

    public void setRegexPath(String regexPath) {
        this.regexPath = regexPath;
    }

    public String getNormStrPath() {
        return normStrPath;
    }

    public void setNormStrPath(String normStrPath) {
        this.normStrPath = normStrPath;
    }

    public String getBoundaryPath() {
        return boundaryPath;
    }

    public void setBoundary(String boundary) {
        this.boundaryPath = boundary;
    }

    public String getCorpPath() {
        return corpPath;
    }

    public Tokenizer getToken() {
        return token;
    }

    public Store getStore() {
        return store;
    }

    public int getN() {
        return n;
    }

    public SuffixArray getSa() {
        return sa;
    }

    public Interval getTop() {
        return top;
    }

    public Concordance getConcord() {
        return concord;
    }

    public ConcordanceOverlap getConcordOver() {
        return concordOver;
    }

    /**
     * Build a SaphreBase object, i.e. 
     * tokenizie, 
     * handle documents,
     * generate the suffix array, 
     * lcp array +
     * and all the other important 
     * data structures.
     * 
     * @return SaphreBase object containing all the relevant stuff.
     */
    public SaphreBase invoke() {
        BoundarySymbols tc;
        Normalizer norm = new GeneralNormalizer(normStrPath);

        token = new RegexTokenizer(regexPath, norm);
        store = new Store(corpPath, token, delMap, "$", " ");
        //A "boundary" is a token that is not allowed to occur in the bridge part
        //between the left part and right part of a gappy phrase.
        tc = new BoundarySymbols(store, boundaryPath);
        store.setTC(tc);
        sa = new SuffixArray(store);
        n = store.text.length - 1;
        top = new Interval(1, n - 1);
        concord = new Concordance(store);
        concordOver = new ConcordanceOverlap(store);
        
        Stopwatch sw = new Stopwatch();
        if (doSerialize) {
            System.out.print("Serializing data files...");
            String serializeFolderPath = corpPath + "/../serialize";
            //System.out.println(serializeFolderPath);
            serMeta = new SaphreSerializerMeta();
            serMeta.setCorpusId(corpusId);
            serMeta.setCorpusPath(corpPath);
            serMeta.setObjPath_store(serializeFolderPath + "/store.ser");
            serMeta.setObjPath_sa(serializeFolderPath + "/sa.ser");
            serMeta.setObjPath_pa(serializeFolderPath + "/pa.ser");
            serMeta.setObjPath_token(serializeFolderPath + "/token.ser");
            serMeta.setObjPath_tc(serializeFolderPath + "/tc.ser");
            serMeta.setObjPath_top(serializeFolderPath + "/top.ser");
            serMeta.setObjPath_concord(serializeFolderPath + "/concord.ser");
            serMeta.setObjPath_concordOver(serializeFolderPath + "/concordOver.ser");

            File file = new File(serializeFolderPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            writeObjectToFile(serMeta.getObjPath_store(), store);
            writeObjectToFile(serMeta.getObjPath_sa(), sa);
            writeObjectToFile(serMeta.getObjPath_pa(), sa.prefixArray());
            writeObjectToFile(serMeta.getObjPath_token(), token);
            writeObjectToFile(serMeta.getObjPath_tc(), tc);
            writeObjectToFile(serMeta.getObjPath_top(), top);
            writeObjectToFile(serMeta.getObjPath_concord(), concord);
            writeObjectToFile(serMeta.getObjPath_concordOver(), concordOver);
        }
        System.out.println(" ...done: " + sw.elapsedTime()  + " seconds.\n\n");
        return this;
    }

    /*
     * 
     */
    private void writeObjectToFile(String path, Object obj) {
        try {
            FileOutputStream fos = null;
            ObjectOutputStream out = null;
            fos = new FileOutputStream(path);
            out = new ObjectOutputStream(fos);
            out.writeObject(obj);
            out.close();
            fos.close();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
